<template>
  <div>
    <el-card style="margin: 10px; height: 85vh">
      <el-button type="primary" size="small" @click="addExamine">
        审批配置
      </el-button>
      <el-dialog title="审批配置" :visible.sync="dialogFormVisible" width="38%">
        <div class="formWrap" style="height: 360px; overflow: auto">
          <div class="formBox">
            <el-form :model="ruleForm" ref="ruleForm" label-width="100px">
              <!-- :prop="'examineArr.' + index + '.examineArrCheck'" -->
              <el-form-item :class="isCount == index ? 'formItem formItems' : 'formItem'"
                v-for="(item, index) in ruleForm.examineArr" :label="digit[index] + '级审批'" :key="index"
                :prop="'examineArr[' + index + '].examineArrCheck'" :rules="{
                  required: true,
                  message: '输入不得为空',
                  trigger: 'blur',
                }" @mouseenter.native="mouseEnter(index)" @mouseleave.native="isCount = 20">
                <el-button class="deleteBtn" size="small" type="info" icon="el-icon-delete" v-if="
                  isCount == index && ruleForm.examineArr.length > 1
                    ? true
                    : false
                " @click="deleteFn(index)">
                </el-button>
                <el-select v-model="item.examineArrCheck" collapse-tags filterable multiple placeholder="请选择">
                  <el-option v-for="(dict, dictIndex) in item.examineArrOptions" :key="dictIndex" :label="dict.label"
                    :value="dict.value">
                    <el-checkbox style="pointer-events: none" :value="item.examineArrCheck.includes(dict.value)">
                      {{ dict.label }}
                    </el-checkbox>
                  </el-option>
                </el-select>
              </el-form-item>
            </el-form>
          </div>
          <el-timeline>
            <el-timeline-item v-for="(val, index) in count" :key="index" color="#0091FF">
              <div style="height: 50px"></div>
            </el-timeline-item>
            <el-timeline-item color="#0091FF" v-if="count == 10 ? false : true">
              <template #dot>
                <el-button icon="el-icon-plus" class="plusBtn" @click="addTimeline">
                </el-button>
              </template>
              添加审批流
            </el-timeline-item>
          </el-timeline>
        </div>
        <div slot="footer" class="dialog-footer">
          <el-button @click="cancel">取 消</el-button>
          <el-button type="primary" @click="submitForm('ruleForm')">确 定</el-button>
        </div>
      </el-dialog>

      <el-upload class="upload-demo" drag name="files" action="1" :http-request="upload" multiple>
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
      </el-upload>
    </el-card>
  </div>
</template>

<script>
import sparkMd5 from "spark-md5";
import axios from "axios";
export default {
  data () {
    return {
      ruleForm: {
        examineArr: [
          {
            examineArrLabel: "一级审批",
            examineArrOptions: [
              {
                value: "选项1",
                label: "选项1",
              },
              {
                value: "选项2",
                label: "选项2",
              },
              {
                value: "选项3",
                label: "选项3",
              },
              {
                value: "选项4",
                label: "选项4",
              },
            ],
            examineArrCheck: [],
          },
        ],
      },

      select: ["选项1", "选项2"],

      value: "",
      dialogFormVisible: false,
      activities: [
        {
          color: "#0091FF",
        },
      ],
      count: 1,
      isCount: 20,
      hashValue: "",
      fileName: "",
      chunkSize: 1024 * 1024 * 10,
      digit: ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十"],
    };
  },
  created () { },
  mounted () { },
  components: {},
  props: {},
  computed: {},
  methods: {
    async upload ({ file }) {
      // console.log(file);
      //文件分片
      let chunks = this.createChunks(file, this.chunkSize);
      //hash计算
      const result = await this.hash(chunks);
      console.log(result, "result");;
      this.hashValue = result;
      this.fileName = file.name;

      const verifyData = await this.verify(); //校验hash值
      console.log(verifyData.data.data, "!!!!");
      if (!verifyData.data.data.shouldUpload) {
        console.log("秒传");
        return;
      }
      //上传分片
      this.uploadChunk(chunks);
    },
    verify () {
      return axios.post("http://127.0.0.1:4567/interface/verify", {
        data: {
          fileName: this.fileName,
          fileHash: this.hashValue,
        },
      });
    },
    async uploadChunk (chunks) {
      // for (let i = 0; i < chunks.length; i++) {
      //   let formdata = new FormData();
      //   formdata.append("file", chunks[i]);
      //   axios
      //     .post("http://127.0.0.1:4567/interface/upload", formdata)
      //     .then((res) => {});
      // }
      const data = chunks.map((chunk, index) => {
        return {
          fileHash: this.hashValue,
          chunkHash: this.hashValue + "-" + index,
          chunk,
        };
      });
      console.log(data);
      const fomrDatas = data.map((item) => {
        const fomrdata = new FormData();
        fomrdata.append("fileHash", item.fileHash);
        fomrdata.append("chunkHash", item.chunkHash);
        fomrdata.append("chunk", item.chunk);
        return fomrdata;
      });
      // console.log(fomrDatas);
      const max = 6; //最大并发请求数
      let index = 0;
      const taskPool = []; //请求池
      while (index < fomrDatas.length) {
        const task = axios.post(
          "http://127.0.0.1:4567/interface/upload1",
          fomrDatas[index]
        );
        taskPool.splice(taskPool.findIndex((item) => item == task));
        taskPool.push(task);
        if (taskPool.length == max) {
          await Promise.race(taskPool);
        }
        index++;
      }
      await Promise.all(taskPool);
      //通知服务器去合并文件

      this.mergeRequest();
    },
    mergeRequest () {
      axios
        .post("http://127.0.0.1:4567/interface/merge", {
          data: {
            fileHash: this.hashValue,
            fileName: this.fileName,
            size: this.chunkSize,
          },
        })
        .then((res) => { });
    },

    hash (chunks) {
      return new Promise((resolve, reject) => {
        const sparkmd5 = new sparkMd5();
        function _read (i) {
          if (i > chunks.length - 1) {
            resolve(sparkmd5.end());
            return;
          }
          const blob = chunks[i]; //分块
          // console.log(chunks[i], "chunks");
          const reader = new FileReader();
          reader.onload = (e) => {
            const bytes = e.target.result; //读取到的字节数
            sparkmd5.append(bytes);
            _read(i + 1);
          };
          reader.readAsArrayBuffer(chunks[i]);
        }
        _read(0);
      });
    },
    createChunks (file, chunkSize) {
      const result = []; //创建分片存储的数组
      for (let i = 0; i < file.size; i += chunkSize) {
        result.push(file.slice(i, i + chunkSize));
      }
      return result; //辅助切片
    },
    getExamine () {
      return this.ruleForm.examineArr.some((item) => {
        if (item.examineArrCheck.length > 0) {
          return true;
        }
      });
    },
    cancel () {
      if (!this.getExamine()) {
        this.dialogFormVisible = false;
        return;
      }
      this.$confirm(
        "您编辑的信息尚未保存，离开后内容将会丢失",
        "确定要离开吗?",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }
      )
        .then(() => {
          this.$message({
            type: "success",
            message: "取消审批!",
          });
          this.dialogFormVisible = false;
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消",
          });
        });
    },
    deleteFn (index) {
      if (this.ruleForm.examineArr[index].examineArrCheck.length) {
        this.$confirm("不可删除在途中的审批节点", "删除失败", {
          confirmButtonText: "我知道了",
          cancelButtonText: "取消",
          type: "error",
        })
          .then(() => { })
          .catch(() => { });
        return;
      }
      this.ruleForm.examineArr.splice(index, 1);
      this.count = this.ruleForm.examineArr.length;
    },
    mouseEnter (index) {
      this.isCount = index;
    },
    addTimeline () {
      this.count++;
      this.ruleForm.examineArr.push({
        examineArrLabel: `${this.digit[this.count - 1]}级审批`,
        examineArrOptions: [
          {
            value: "选项1",
            label: "选项1",
          },
          {
            value: "选项2",
            label: "选项2",
          },
          {
            value: "选项3",
            label: "选项3",
          },
          {
            value: "选项4",
            label: "选项4",
          },
        ],
        examineArrCheck: [],
      });
    },
    addExamine () {
      this.dialogFormVisible = true;
      this.count = 1;
      Object.assign(this.ruleForm, {
        examineArr: [
          {
            examineArrLabel: "一级审批",
            examineArrOptions: [
              {
                value: "选项1",
                label: "选项1",
              },
              {
                value: "选项2",
                label: "选项2",
              },
              {
                value: "选项3",
                label: "选项3",
              },
              {
                value: "选项4",
                label: "选项4",
              },
            ],
            examineArrCheck: [],
          },
        ],
      });
    },
    submitForm (formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          this.$message({
            type: "success",
            message: "操作成功",
          });
          this.dialogFormVisible = false;
        } else {
          return false;
        }
      });
    },
  },
};
</script>
<style scoped lang="scss">
.plusBtn {
  display: block;
  width: 20px;
  height: 20px;
  margin-left: -10px;
  text-align: center;
  line-height: 20px;
  border-radius: 50%;
  color: white;
  background: #0091ff;
  padding: 0;
  margin: 0;
}

.formWrap {
  position: relative;

  .formBox {
    width: 80%;
    left: 46px;
    z-index: 999;
    position: absolute;

    .formItem {
      height: 78px;
      margin-bottom: 0;
      position: relative;
      margin-left: 20px;

      .deleteBtn {
        position: absolute;
        top: 0;
        right: 0;
        z-index: 500;
        background: none;
        border: 0;
      }
    }

    .formItems {
      background: #90939954;
    }
  }
}
</style>
